package Twitim::API;

use strict;
use warnings;

use AnyEvent;
use HTML::Entities;
use JSON::XS;
use POSIX qw(_exit);
use IO::Handle;

# use Data::Dumper;
use Twitim::API::OAuth;
use base qw(Twitim::NetBase);

sub new {
    my $this  = shift;
    my $class = ref($this) || $this;
    my $self  = { twitter_url => 'http://api.twitter.com/1/', @_ };

    $self->{'protocol'} = 'Twitter API';
    $self->{'cb'}->{'message'} ||= sub { $self->_message(@_) };

    $self->{'access_token'}  ||= "";
    $self->{'access_secret'} ||= "";

    return bless $self, $class;
}

sub get {
    my ( $self, $output, $reply_id ) = @_;
    $self->_start( $output, $reply_id );
    $self->_process();
}

sub _start2 {
    print "start\n";
}

sub _process {
    my $self = shift;

#    print "processing...\n";
}

sub _last {
    # other timeline
    my ( $self, $array_ref, $output, $api ) = @_;
    my $num = 0;
    # print "\n";

    @{$array_ref} = sort { $a->{'id'} <=> $b->{'id'}; } @{$array_ref};

    foreach my $hash_ref (@$array_ref) {

        # for track message's user name.
        # $jid = $option if ( defined $option and $option =~ /\(.*\)/ );

        my $jid  = $hash_ref->{'user'}{'screen_name'};
        my $id   = $hash_ref->{'id'};
        my $body = $hash_ref->{'text'};
        my $time = $self->get_unixtime( $hash_ref->{'created_at'} );
        my $source    = $hash_ref->{'source'};
        my $favorited = $hash_ref->{'favorited'};

        Twitim::NetBase->set_username( $jid, $hash_ref->{'user'}{'name'} );
        Twitim::NetBase->set_userid( $jid, $hash_ref->{'user'}{'id'} );
        Twitim::NetBase->set_icon( $jid,
            $hash_ref->{'user'}{'profile_image_url'} );
        Twitim::NetBase->set_favorites( $id, $favorited ) if $favorited;

#        print Dumper($hash_ref) . "\n";
#
        return if ( defined $output && $output eq 'none' );    #fixme: need?

        my $my_id = Twitim::NetBase->get_my_id;

        $self->{'cb'}->{'message'}->(
            {   user_id    => $jid,
                body       => decode_entities($body),
                message_id => $id,
                unixtime   => $time,
                source     => $source,
                favorited  => $favorited,
                output     => $output
            }
            );

    }

    return;
}

sub _getfromapi {
    my ( $self, $api, $api_arg, $output, $extra ) = @_;

    if (   !$self->{'userid'}
        || !$self->{'access_token'}
        || !$self->{'access_secret'} )
    {
        #$self->set_error( $self->_l10n('No account is configured') );
        return;
    }

    pipe( my $read_fh, my $write_fh );
    binmode( $read_fh,  ':utf8' );
    binmode( $write_fh, ':utf8' );
    $write_fh->autoflush(1);

    if ( my $pid = fork ) {
        close $write_fh;
        my $tag;
        $tag = AnyEvent->io(
            fh   => $read_fh,
            poll => 'r',
            cb   => sub {
                my $data = <$read_fh>;
                $self->_interpret_api( \$data, $api, $output ) if $data;
                undef $tag;
            }
        );
    }
    elsif ( defined $pid ) {
        $SIG{'INT'} = $SIG{'TERM'} = 'DEFAULT';
        close $read_fh;

        my $url = $self->{'twitter_url'} . $api . $api_arg;
        my $method = ( $api =~ /(update|create|destroy|retweet)/ ) ? 'POST' : 'GET';

        my $oauth = Twitim::API::OAuth->new;
        my $http_req = $oauth->make_http_request(
            $method, $url, $extra,
            $self->{'access_token'},
            $self->{'access_secret'},
        );
        my ( $res, $timeout ) = $self->get_http($http_req);

        my $content;
        if ($timeout) {
            $content = $self->_l10n("No response from server");
        }
        else {
            my $code = $res->code;
            $content = $res->content;

            # no json nor text
            $content = sprintf( $self->_l10n("%d (Detail unknown)"), $code )
                if ( $code > 400 && $content =~ /^ *</ );
        }

        print {$write_fh} $content;
        close $write_fh;

        _exit(1);
    }
}

sub _interpret_api {
    my ( $self, $data_ref, $api, $output ) = @_;

    # for Malformed JSON
    warn "Malformed JSON!\n" if $$data_ref =~ m{find Status};
    $$data_ref =~ s{Couldn't find Status with ID=[0-9],}{}g;

    # no json
    if ( $$data_ref =~ /^ *[^{\[]/ ) {

        #        $self->set_error($$data_ref) if $$data_ref !~ m{^\s+$};
        return;
    }

    $$data_ref =~ s/NULL/null/;
    my $array_ref = decode_json $$data_ref;

    # check api error
    if ( ref($array_ref) eq "HASH" ) {
        foreach my $key (%$array_ref) {
            if ( $key && $key =~ /error/i ) {

                #                $self->set_error( $array_ref->{'error'} );
                last;
            }
        }
        return
            if ( $api ne 'account/rate_limit_status'
            && $api ne 'users/show' );
    }

    # $self->set_error(); # yendo
    # print Dumper(@{$array_ref}) . "\n";

    #print $$data_ref, "\n";
    $self->_last( $array_ref, $output, $api );

    return;
}

1;
